<?php

declare(strict_types=1);

namespace Plugin\Attractions\AttractionManagement\Service;

use App\Exception\BusinessException;
use App\Http\Common\ResultCode;
use Common\Common;
use Hyperf\DbConnection\Db;
use Hyperf\Di\Annotation\Inject;
use Plugin\Attractions\AttractionManagement\Repository\AttractionScoreRepository;
use Plugin\Attractions\AttractionManagement\Repository\AttractionSpotPositionRepository;
use Plugin\Attractions\AttractionManagement\Repository\AttractionSpotRepository;
use Plugin\Attractions\AttractionManagement\Repository\AttractionSpotTagRepository;
use Plugin\Attractions\AttractionManagement\Repository\AttractionTypeRepository;
use Psr\Log\LogLevel;

class SpotService
{
    #[Inject]
    protected AttractionSpotRepository $repository;
    #[Inject]
    protected AttractionSpotPositionRepository $positionRepository;
    #[Inject]
    protected AttractionTypeRepository $typeRepository;
    #[Inject]
    protected AttractionSpotTagRepository $tagsRepository;
    #[Inject]
    protected AttractionScoreRepository $scoreRepository;

    public function page(array $params): array
    {
        $result = $this->repository->showListPage($params);
        $score = $this->scoreRepository->getScoreList();
        array_map(function ($item) use ($score) {
            $item->score = $score[$item['id']] ?? '5.0';
            return $item;
        }, $result);
        return $result;
    }

    public function create(array $data): array
    {
        if (!$this->typeRepository->isValidType($data['typeId'])) {
            throw new BusinessException(ResultCode::UNPROCESSABLE_ENTITY, trans('attraction-management.info.notType'));
        }
        Db::beginTransaction();
        try {
            // 添加位置
            if (isset($data['position'])) {
                $position = $this->positionRepository->create([
                    'name' => $data['position']['name'] ?? '',
                    'longitude' => $data['position']['longitude'],
                    'latitude' => $data['position']['latitude'],
                    'altitude' => $data['position']['altitude'],
                ]);
            }

            $res = $this->repository->create([
                'name' => $data['name'],
                'type_id' => $data['typeId'],
                'position_id' => $position->id?? 0,
                'intro_title' => $data['introTitle'] ?? '',
                'intro' => $data['intro'] ?? '',
                'attraction_id' => $data['attractionId'],
                'cover_id' => $data['coverId'] ?? 0,
                'show_type' => $data['showType'] ?? 1,
                'icon_id' => $data['iconId'] ?? 0,
                'status' => $data['status'] ?? 0,
                'sort' => $data['sort'] ?? 0,
                'extension' => $data['extension'] ?? [],
            ]);
            if (isset($data['tags']) && !empty($data['tags'])) {
                // 添加标签
                $this->tagsRepository->insert($data['tags'], $res->id);
            }
            Db::commit();
            return $res->toArray();
        } catch (\Throwable $e) {
            Db::rollBack();
            Common::log(__CLASS__, 'line:' . $e->getLine() . ' message:' . $e->getMessage());
            return [];
        }
    }

    public function delete(array $id): int
    {
        $deleteIds = $this->repository->listDeleteIds(['id' => $id]);
        Db::beginTransaction();
        try {
            // 删除位置
            $this->positionRepository->deleteById($deleteIds['position']);
            // 删除标签
            $this->tagsRepository->deleteBySpotId($id);
            // 删除点位
            $res = $this->repository->deleteById($id);
            Db::commit();
        } catch (\Throwable $e) {
            Db::rollBack();
            Common::log(__CLASS__, 'line:' . $e->getLine() . ' message:' . $e->getMessage());
            return 0;
        }
        return $res;
    }

    public function update(array $ids, array $data): bool
    {
        Db::beginTransaction();
        try {
            // 点位位置信息更新
            if (isset($data['position'])) {
                if (count($ids) != 1) {
                    throw new BusinessException(ResultCode::UNPROCESSABLE_ENTITY, trans('attraction-management.spot.position.notBatch'));
                }
                $spot = $this->repository->findById($ids[0]);
                if (! $spot) {
                    throw new BusinessException(ResultCode::NOT_FOUND, trans('attraction-management.spot.notFound'));
                }
                $this->positionRepository->updatebyId($spot->position_id, $data['position']);
            }
            $updateData = [];
            // 驼峰转下划线
            foreach ($data as $key => $value) {
                $updateData[strtolower(preg_replace('/(?<!^)[A-Z]/', '_$0', $key))] = $value;
            }
            $res = $this->repository->updateById($ids, $updateData);
            Db::commit();
        } catch (\Throwable $e) {
            Db::rollBack();
            Common::log(__CLASS__, 'line:' . $e->getLine() . ' message:' . $e->getMessage(), LogLevel::ERROR);
            return false;
        }
        return $res;
    }

    public function detail(int $id): array
    {
        return $this->repository->getDetail($id);
    }
}
